package com.snack.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snack.common.result.Result;
import com.snack.entity.dto.OrderDTO;
import com.snack.entity.dto.OrderDetailsDTO;
import com.snack.entity.dto.OrderSnackDTO;
import com.snack.entity.pojo.Member;
import com.snack.entity.pojo.Order;
import com.snack.entity.pojo.OrderSnack;
import com.snack.entity.pojo.Snack;
import com.snack.mapper.OrderMapper;
import com.snack.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author huangfuhao
 * @Date 2025/3/30
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {


    @Resource
    private OrderSnackService orderSnackService;

    @Resource
    private SnackService snackService;

    @Resource
    private StoreService storeService;

    @Resource
    private MemberService memberService;

    @Override
    @Transactional
    public Result addOrder(OrderDTO orderDTO) {

        //拿到处理订单的店铺id
        Long storeId = storeService.getStoreIdByUser();


        log.info("生成订单接口：{}", orderDTO);
        //需要先计算所有零食的总价格
        List<Snack> snackList = orderDTO.getSnackList();

        //通过循环去计算每种零食的价格和数量并加在一起
        float totalAmount = 0f;
        for (Snack snack : snackList) {
            Integer inventory = snack.getInventory();
            Float price = snack.getPrice();
            totalAmount += inventory * price;
        }
        //先拿到会员id，判断有没有会员
        Long userId = orderDTO.getUserId();
        if (userId != null) {
            // 有会员，拿出会员信息
            Member member = memberService.getById(userId);
            Integer points = member.getPoints(); // 拿出会员积分
            // 得出原始订单金额totalAmount，积分按照100比1抵扣价格，积分不足，则不能使用积分抵扣，且最终totalAmount需要大于0
            if (points > 0) {
                // 计算可以抵扣的最大金额
                float maxDeductionAmount = points / 100.0f;
                // 计算实际需要抵扣的金额
                float deductionAmount = Math.min(maxDeductionAmount, totalAmount);
                // 计算抵扣后的订单金额
                float newTotalAmount = totalAmount - deductionAmount;

                if (newTotalAmount >= 0) {
                    // 更新订单金额
                    totalAmount = newTotalAmount;
                    // 计算剩余积分
                    int remainingPoints = points - (int) (deductionAmount * 100);
                    member.setPoints(remainingPoints);
                    memberService.updateById(member);
                }
            }
        }

        orderDTO.setTotalAmount(totalAmount);
        orderDTO.setStoreId(storeId);
        orderDTO.setOrderDate(LocalDateTime.now());
        orderDTO.setStatus(0);
        // 将订单数据记录在order表,获取订单id
        save(orderDTO);
        Long orderId = orderDTO.getId();


        //记录订单和零食的对应数据在order_snack表
        List<OrderSnack> orderSnackList = snackList.stream().map(snack -> {
            OrderSnack orderSnack = new OrderSnack();
            Integer snackId = snack.getId();
            Integer inventory = snack.getInventory();
            orderSnack.setOrderId(orderId);
            orderSnack.setSnackId(snackId);
            orderSnack.setQuantity(inventory);
            //顺便扣除库存
            snackService.lambdaUpdate().eq(Snack::getId, snackId).setSql("inventory = inventory -" + inventory).update();
            return orderSnack;
        }).toList();

        //批量将数据保存到order_snacks表中
        orderSnackService.saveBatch(orderSnackList);


        return Result.success(orderDTO);
    }


    @Override
    public Result listOrder(Order order) {
        // 查询店铺下订单列表，可以根据用户id查询其消费记录，也可以根据订单id查询其消费记录
        Long storeId = storeService.getStoreIdByUser();

        // 使用LambdaQueryWrapper构建查询条件
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getStoreId, storeId);

        // 添加userId查询条件
        if (order.getUserId() != null) {
            queryWrapper.eq(Order::getUserId, order.getUserId());
        }

        // 添加status查询条件
        if (order.getStatus() != null) {
            queryWrapper.eq(Order::getStatus, order.getStatus());
        }

        // 添加state查询条件
        if (order.getStatus() != null) {
            queryWrapper.eq(Order::getStatus, order.getStatus());
        }

        // 添加orderDate查询条件，这里假设orderDate是一个字符串，并且我们进行模糊查询
        LocalDateTime orderDate = order.getOrderDate();
        if (orderDate != null) {
            // 构建从当天开始到当天结束的时间范围
            LocalDateTime startDate = orderDate.toLocalDate().atStartOfDay();
            LocalDateTime endDate = orderDate.toLocalDate().plusDays(1).atStartOfDay();

            // 使用between方法查询指定日期范围内的订单
            queryWrapper.between(Order::getOrderDate, startDate, endDate);
        }

        List<Order> list = list(queryWrapper);

        return Result.success(list);
    }

    //查看订单详情，根据订单ID获取到订单内的零食
    @Override
    public Result getOrderDetails(Order order1) {
        // 根据orderId查询订单信息
        Order order = getById(order1.getId());
        if (order == null) {
            return Result.error("订单不存在");
        }

        // 根据orderId查询order_snack表获取订单内的零食信息
        LambdaQueryWrapper<OrderSnack> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderSnack::getOrderId, order1.getId());
        List<OrderSnack> orderSnackList = orderSnackService.list(queryWrapper);

        // 将OrderSnack对象转换为DTO或其他需要的格式
        List<OrderSnackDTO> orderSnackDTOList = orderSnackList.stream().map(orderSnack -> {
            OrderSnackDTO orderSnackDTO = new OrderSnackDTO();
            orderSnackDTO.setOrderId(orderSnack.getOrderId());
            orderSnackDTO.setSnackId(orderSnack.getSnackId());
            orderSnackDTO.setQuantity(orderSnack.getQuantity());

            // 获取零食的详细信息
            Snack snack = snackService.getById(orderSnack.getSnackId());
            if (snack != null) {
                orderSnackDTO.setSnackName(snack.getName());
                orderSnackDTO.setSnackPrice(snack.getPrice());
            }

            return orderSnackDTO;
        }).toList();

        // 将订单信息和订单内的零食信息封装到一个DTO中
        OrderDetailsDTO orderDetailsDTO = new OrderDetailsDTO();
        orderDetailsDTO.setOrder(order);
        orderDetailsDTO.setOrderSnackList(orderSnackDTOList);

        return Result.success(orderDetailsDTO);
    }

    @Override
    public Result listOrdersByConsumerPhone(Member member) {
        // 校验输入参数是否为空
        if (member == null || StringUtils.isEmpty(member.getPhone())) {
            return Result.error("会员信息不能为空或电话号码无效");
        }

        // 获取电话号码并查询会员信息
        String phone = member.getPhone();
        Member member1 = memberService.lambdaQuery().eq(Member::getPhone, phone).one();

        // 判断会员是否存在
        if (member1 == null) {
            return Result.error("未找到与该电话号码关联的会员信息");
        }

        // 获取用户ID并查询订单信息
        Long userId = member1.getUserId();
        if (userId == null) {
            return Result.error("会员用户ID为空，无法查询订单信息");
        }

        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getUserId, userId);
        List<Order> orderList = list(queryWrapper);

        // 判断订单列表是否为空
        if (orderList == null || orderList.isEmpty()) {
            return Result.success(Collections.emptyList()); // 返回空列表而非null
        }

        // 返回成功结果
        return Result.success(orderList);
    }

    @Override
    public Result deleteInventory(OrderDTO orderDTO) {
        //拿到处理订单的店铺id
        Long storeId = storeService.getStoreIdByUser();

        log.info("库存销毁接口：{}", orderDTO);
        //需要先计算所有零食的总价格
        List<Snack> snackList = orderDTO.getSnackList();

        //通过循环去计算每种零食的价格和数量并加在一起
        float totalAmount = 0f;
        for (Snack snack : snackList) {
            Integer inventory = snack.getInventory();
            Float price = snack.getPrice();
            totalAmount += inventory * price;
        }

        orderDTO.setTotalAmount(totalAmount);
        orderDTO.setStoreId(storeId);
        orderDTO.setOrderDate(LocalDateTime.now());
        orderDTO.setStatus(2);
        //将订单数据记录在order表,获取订单id
        save(orderDTO);
        Long orderId = orderDTO.getId();


        //记录订单和零食的对应数据在order_snack表
        List<OrderSnack> orderSnackList = snackList.stream().map(snack -> {
            OrderSnack orderSnack = new OrderSnack();
            Integer snackId = snack.getId();
            Integer inventory = snack.getInventory();
            orderSnack.setOrderId(orderId);
            orderSnack.setSnackId(snackId);
            orderSnack.setQuantity(inventory);
            //顺便扣除库存
            snackService.lambdaUpdate().eq(Snack::getId, snackId).setSql("inventory = inventory -" + inventory).update();
            return orderSnack;
        }).toList();

        //批量将数据保存到order_snacks表中
        orderSnackService.saveBatch(orderSnackList);

        return Result.success(orderDTO);

    }

    @Override
    @Transactional
    public Result deleteOrder(Order order) {
        log.info("删除订单：{}", order);

        // 根据订单ID查询订单是否存在
        Long orderId = order.getId();
        Order existingOrder = getById(orderId);

        if (existingOrder == null) {
            return Result.error("订单不存在");
        }

        // 根据订单ID查询订单内的零食信息
        LambdaQueryWrapper<OrderSnack> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderSnack::getOrderId, orderId);
        List<OrderSnack> orderSnackList = orderSnackService.list(queryWrapper);

        if (orderSnackList == null || orderSnackList.isEmpty()) {
            return Result.error("订单内没有零食信息");
        }

        // 还原零食库存
        for (OrderSnack orderSnack : orderSnackList) {
            Integer snackId = orderSnack.getSnackId();
            Integer quantity = orderSnack.getQuantity();

            // 还原零食库存
            boolean updateInventory = snackService.lambdaUpdate()
                    .eq(Snack::getId, snackId)
                    .setSql("inventory = inventory + " + quantity)
                    .update();
            if (!updateInventory) {
                return Result.error("还原零食库存失败");
            }
        }

        // 删除订单内的零食信息
        boolean deleteOrderSnacks = orderSnackService.remove(queryWrapper);
        if (!deleteOrderSnacks) {
            return Result.error("删除订单内的零食信息失败");
        }

        // 删除订单
        boolean deleteOrder = removeById(orderId);
        if (!deleteOrder) {
            return Result.error("删除订单失败");
        }

        return Result.success("订单删除成功");
    }


}